/* vim: set ts=2 et sw=2 cindent fo=qroca: */

package com.globant.google.mendoza;

import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.globant.google.mendoza.malbec.schema._2.MerchantCalculationCallback;
import com.globant.google.mendoza.malbec.schema._2.MerchantCalculationResults;

/** Represents the information related to a merchant calculation. Contains the
 * merchant calculation callback, the merchant calculation result and the
 * timing of the calculation.
 */
public final class MendozaMerchantCalculation implements Comparable {

  /** The class logger.  */
  private static Log log = LogFactory.getLog(
      MendozaMerchantCalculation.class);

  /** The callback message. */
  private String callbackMsg;

  /** The merchant calculation callback. */
  private MerchantCalculationCallback merchantCalculationCallback;

  /** The result message. */
  private String resultMsg;

  /** The merchant calculation result. */
  private MerchantCalculationResults merchantCalculationResult;

  /** The start time. */
  private Date startTime;

  /** The end time.  */
  private Date endTime;

  /** The result of validating the calculation result XML with the schema.
   */
  private String calculationResultSchemaValidation;

  /** The validation result. */
  private MendozaMerchantCalculationValidation validation;

  /** Constructor. Creates an instance of MerchantCalculation.
   *
   * @param theCallbackMsg The callback message.
   *
   * @param theMerchantCalculationCallback The callback object.
   *
   * @param theResultMsg The result message.
   *
   * @param theMerchantCalculationResult The result object.
   *
   * @param theStartTime Calculation start time.
   *
   * @param theEndTime Calculation end time.
   *
   * @param mcValidator The merchant calculation validator.
   */
   public MendozaMerchantCalculation(final String theCallbackMsg,
    final MerchantCalculationCallback theMerchantCalculationCallback,
    final String theResultMsg,
    final MerchantCalculationResults theMerchantCalculationResult,
    final Date theStartTime, final Date theEndTime,
    final MendozaMerchantCalculationValidator mcValidator) {

    callbackMsg = theCallbackMsg;
    merchantCalculationCallback = theMerchantCalculationCallback;
    resultMsg = theResultMsg;
    merchantCalculationResult = theMerchantCalculationResult;
    startTime = theStartTime;
    endTime = theEndTime;

    if (mcValidator != null && merchantCalculationResult != null) {
      validation = mcValidator.validate(this);
    }
 }

  /** Gets the merchant calculation validation.
   *
   * @return Returns the merchant calculation validation.
   */
  public MendozaMerchantCalculationValidation getValidation() {
    return validation;
  }

  /** Gets the callback message.
   *
   * @return Returns the callback message.
   */
  public String getCallbackMsg() {
    return callbackMsg;
  }

  /** Gets the callback.
   *
   * @return Returns the callback.
   */
  public MerchantCalculationCallback getMerchantCalculationCallback() {
    return merchantCalculationCallback;
  }

  /** Gets the result message.
   *
   * @return Returns the result message.
   */
  public String getResultMsg() {
    return resultMsg;
  }

  /** Gets the result.
   *
   * @return Returns the result.
   */
  public MerchantCalculationResults getMerchantCalculationResult() {
    return merchantCalculationResult;
  }

  /** Gets the start time.
   *
   * @return Returns the start time.
   */
  public Date getStartTime() {
    return startTime;
  }

  /** Gets the end time.
   *
   * @return Returns the end time.
   */
  public Date getEndTime() {
    return endTime;
  }

  /** Compares two MerchantCalculation objects.
   *
   * @param anotherMerchantCalculation The other merchant calculation to
   * compare with.
   *
   * @return Returns the comparation result.
   */
  public int compareTo(final Object anotherMerchantCalculation) {
    log.trace("Entering compareTo");
    if (!(anotherMerchantCalculation
        instanceof MendozaMerchantCalculation)) {
        throw new ClassCastException("A MerchantCalculation object expected.");
    }
    Date startTimeAsDate =
         ((MendozaMerchantCalculation)
             anotherMerchantCalculation).getStartTime();
    long anotherMerchantCalculationStartTime = startTimeAsDate.getTime();
    long result =
         getStartTime().getTime() - anotherMerchantCalculationStartTime;
    log.trace("Leaving compareTo");
    return (int) Long.valueOf(result).intValue();
  }

  /** Gets the merchant calculation information.
   *
   * @return Returns a string description of this calculation.
   */
  public String toString() {
    StringBuffer sf = new StringBuffer();
    String callbackString = callbackMsg;
    callbackString = callbackString.replace("><", ">\n<");
    sf.append(">>Callback: \n");
    sf.append(callbackString);
    String resultString = resultMsg;
    resultString = resultString.replace("><", ">\n<");
    sf.append("\n\n>>Result: \n");
    sf.append("\n");
    sf.append(getResultSchemaValidation());
    sf.append("\n\n");
    sf.append(resultString);
    sf.append("\n>>Total time: ");
    sf.append(getCalculationTime());
    sf.append(" milliseconds.");
    sf.append("\n");
    if (merchantCalculationResult != null) {
      sf.append(getValidation());
    }
    return sf.toString();
  }

  /** The calculation time.
   *
   * @return The calculation time.
   */
  public long getCalculationTime() {
    return endTime.getTime() - startTime.getTime();
  }

  /** Gets the validation of the result message with the schema.
   *
   * @return The validation message.
   */
  public String getResultSchemaValidation() {
    return calculationResultSchemaValidation;
  }

  /** Sets the validation of the result message with the schema.
   *
   * @param schemaValidation The validation message.
   */
  public void setResultSchemaValidation(
      final String schemaValidation) {
    calculationResultSchemaValidation = schemaValidation;
  }
}
